package com.smu.recognize.controller;

import com.arcsoft.face.FaceFeature;
import com.arcsoft.face.FaceSimilar;
import com.smu.recognize.Util.CurrentTimeUtil;
import com.smu.recognize.Util.DateCompare;
import com.smu.recognize.Util.Distance;
import com.smu.recognize.faceCompare.FeatureCompare;
import com.smu.recognize.model.Apply;
import com.smu.recognize.model.AttConfig;
import com.smu.recognize.model.Attendance;
import com.smu.recognize.model.common.JsonResult;
import com.smu.recognize.model.common.JsonReturn;
import com.smu.recognize.service.ApplyService;
import com.smu.recognize.service.AttendanceService;
import com.smu.recognize.service.ConfigService;
import com.smu.recognize.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/*
*
* 这里的考勤时间设置的不对！！！！！！！！！！
*
* */
//http://192.168.101.14:8085/insertAtt?user_id=1&date=2021.2.20&start_time=08:40;end_time=17:30&address=%E5%AE%89%E5%BE%BD%E6%BB%81%E5%B7%9E%E5%8D%97%E8%B0%AF%E5%8C%BA%E5%8C%97%E6%B9%96%E5%B0%8F%E5%8C%BA&longitude=70&latitude=80&flag=1&status=1
@RestController
@Slf4j
@CrossOrigin(originPatterns = "*", allowCredentials = "true", allowedHeaders = "*", methods = {})
public class AttendanceController {
    //上海海事大学信息工程学院的经纬度
    public static double longitude = 121.905411;//
    public static double latitude = 30.876277;
    String startTime;
    //标准下班时间
    String endTime;
    int address_range;

    List<Attendance> list = new ArrayList<>();
    List<Attendance> dayAttList = new ArrayList<>();
    List<Apply> applyList = new ArrayList<>();

    Attendance attendance = new Attendance();
    @Autowired
    private AttendanceService attService;

    @Autowired
    private UserService userService;

    @Autowired
    private ApplyService applyService;

    @Autowired
    private ConfigService configService;

    List<AttConfig> configList = new ArrayList<>();

    @RequestMapping("/insertAtt")
    public boolean insert(Attendance attendance) {
        //考勤成功的标志
        boolean success = false;
        AttConfig aConfig = new AttConfig();
        //查找配置表中的配置
        configList = configService.findAll();
        for (AttConfig attConfig : configList) {
            if (attConfig.getStatus() == 1) {
                aConfig = attConfig;
            }
        }
        //配置表中没有找到启用的配置，使用默认配置
        if (aConfig.getStatus() != 1) {
            log.info("考勤配置表未启用");
            //标准上班考勤时间
            startTime = attendance.getDate() + " 09:35:00";
            //标准下班时间
            endTime = attendance.getDate() + " 19:29:00";
            address_range = 1000;
        } else {
            log.info("考勤配置表" + aConfig.getC_id() + "启用");
            longitude = Double.parseDouble(aConfig.getLongitude());
            latitude = Double.parseDouble(aConfig.getLatitude());

            startTime = attendance.getDate() + " " + aConfig.getStart_time();
            //标准下班时间
            endTime = attendance.getDate() + " " + aConfig.getEnd_time();
            address_range = aConfig.getAddress_range();
        }
        //内勤外勤的标志
        int flag = attendance.getFlag();
        //实际时间，待插入的记录时间
        String Time = attendance.getDate() + " " + attendance.getTime();
        GlobalCoordinates source = new GlobalCoordinates(latitude, longitude);
        //内勤
        if (flag == 0) {
            /*
             * 这里需要对考勤的情况进行细分
             * 地点
             * flag：内勤（0）、外勤（1）、地点距离太远
             * 时间
             * status：正常（1）：
             *         不正常（0）：位置不对
             * describe：迟到、早退、缺勤
             *签到签退
             *
             * 上班时间 9：30
             * 下班时间 21：30
             *
             * 上班地点、上海海事大学信息工程学院
             * */
            //考勤位置的经纬度
            GlobalCoordinates to = new GlobalCoordinates(Double.valueOf(attendance.getLatitude()), Double.valueOf(attendance.getLongitude()));
            //考勤位置与上海海事大学之间的距离,可以使用不同的坐标系取平均值
            double distance = Distance.getDistanceMeter(source, to, Ellipsoid.Sphere);
            double distance1 = Distance.getDistanceMeter(source, to, Ellipsoid.WGS84);
            double distance2 = Distance.getDistanceMeter(source, to, Ellipsoid.WGS72);
            log.info("distance" + distance + "\n"
                    + "distance1" + distance1
                    + "distance2" + distance2);

            dayAttList = attService.findByIdAndDate(attendance.getUser_id(), attendance.getDate(), 1);
            //签到
            if (dayAttList.size() == 0) {
                //上班时间是否在规定时间之前
                boolean before = DateCompare.isDateBefore(Time, startTime);
                //迟到
                if (!before) {
                    attendance.setDescribed("迟到");
                } else {
                    attendance.setDescribed("正常");
                }//正常
                attendance.setStatus(1);

                //距离超过配置距离考勤失败
                if (distance >= address_range) {
                    attendance.setStatus(0);
                    attendance.setDescribed("签到位置异常");
                    attService.insertAttendance(attendance);
                    return false;
                }
                success = attService.insertAttendance(attendance);
                return success;
            } else if (dayAttList.size() == 1) {
                //标准下班时间是否在下班时间之前,判断时间date1是否在时间date2之
                boolean before = DateCompare.isDateBefore(endTime, Time);
                //早退
                if (!before) {
                    attendance.setDescribed("早退");
                }//正常
                else {
                    attendance.setDescribed("正常");
                }
                attendance.setStatus(1);
                //距离超过1km考勤失败
                if (distance >= address_range) {
                    attendance.setStatus(0);
                    attendance.setDescribed("位置异常");
                    attService.insertAttendance(attendance);
                    return false;
                }

                success = attService.insertAttendance(attendance);
                return success;
            } else {
                log.info("重复签到");
                return false;
            }
        } else {
            //外勤，不计算距离，只判断时间
            dayAttList = attService.findByIdAndDate(attendance.getUser_id(), attendance.getDate(), 1);
            attendance.setStatus(1);
            //签到
            if (dayAttList.size() == 0) {
                //上班时间是否在规定时间之前
                boolean before = DateCompare.isDateBefore(Time, startTime);
                //迟到
                if (!before) {
                    attendance.setDescribed("迟到");
                }//正常
                else {
                    attendance.setDescribed("正常");
                }
                success = attService.insertAttendance(attendance);
                return success;
            } else if (dayAttList.size() == 1) {
                /**
                 * 首先判断要插入的记录和第一条记录哪条是上班，哪条是下班
                 * time是待插入的记录，dayAttList
                 * 判断时间date1是否在时间date2之前
                 */
                boolean morning = DateCompare.isDateBefore(Time, attendance.getDate() + " " + dayAttList.get(0).getTime());
                //补卡的记录是上班记录
                //插入上班记录，更新dayAttList(0)的describe();
                if (morning) {
                    //上班时间是否在规定时间之前
                    boolean before = DateCompare.isDateBefore(Time, startTime);
                    //迟到
                    if (!before) {
                        attendance.setDescribed("迟到");
                    }//正常
                    else {
                        attendance.setDescribed("正常");
                    }
                    //判断dayAttList(0)的下班时间
                    //上班时间是否在规定时间之前
                    boolean after = DateCompare.isDateBefore(endTime, dayAttList.get(0).getTime());
                    //迟到
                    if (!after) {
                        dayAttList.get(0).setDescribed("早退");
                    }//正常
                    else {
                        dayAttList.get(0).setDescribed("正常");
                    }
                    //版本升级的时候把这个定义为事务来做
                    success = attService.insertAttendance(attendance);
                    boolean success1 = attService.updateAttendacne(dayAttList.get(0));
                    return success && success1;
                } else {//补卡是下班记录
                    boolean after = DateCompare.isDateBefore(endTime, Time);
                    //迟到
                    if (!after) {
                        attendance.setDescribed("早退");
                    }//正常
                    else {
                        attendance.setDescribed("正常");
                    }
                    success = attService.insertAttendance(attendance);
                    return success;
                }
            } else {
                log.info("重复签到");
                return false;
            }
        }
    }

    @RequestMapping("/web/insertAtt")
    public JsonReturn insertWebAtt(Attendance attendance) {
        //考勤成功的标志
        boolean success = false;
        AttConfig aConfig = new AttConfig();
        //查找配置表中的配置
        configList = configService.findAll();
        for (AttConfig attConfig : configList) {
            if (attConfig.getStatus() == 1) {
                aConfig = attConfig;
            }
        }
        //配置表中没有找到启用的配置，使用默认配置
        if (aConfig.getStatus() != 1) {
            log.info("考勤配置表未启用");
            //标准上班考勤时间
            startTime = attendance.getDate() + " 09:35:00";
            //标准下班时间
            endTime = attendance.getDate() + " 19:29:00";
            address_range = 1000;
        } else {
            log.info("考勤配置表" + aConfig.getC_id() + "启用");
            longitude = Double.parseDouble(aConfig.getLatitude());
            latitude = Double.parseDouble(aConfig.getLatitude());
            startTime = attendance.getDate() + " " + aConfig.getStart_time();
            //标准下班时间
            endTime = attendance.getDate() + " " + aConfig.getEnd_time();
            address_range = aConfig.getAddress_range();
        }
        //内勤外勤的标志
        int flag = attendance.getFlag();
        //实际时间
        String Time = attendance.getDate() + " " + attendance.getTime();

        GlobalCoordinates source = new GlobalCoordinates(latitude, longitude);
        //内勤
        if (flag == 0) {
            /*
             * 这里需要对考勤的情况进行细分
             * 地点
             * flag：内勤（0）、外勤（1）、地点距离太远
             * 时间
             * status：正常（1）：
             *         不正常（0）：位置不对
             * describe：迟到、早退、缺勤
             *签到签退
             *
             * 上班时间 9：30
             * 下班时间 21：30
             *
             * 上班地点、上海海事大学信息工程学院
             * */
            //考勤位置的经纬度
            GlobalCoordinates to = new GlobalCoordinates(Double.valueOf(attendance.getLatitude()), Double.valueOf(attendance.getLongitude()));
            //考勤位置与上海海事大学之间的距离,可以使用不同的坐标系取平均值
            double distance = Distance.getDistanceMeter(source, to, Ellipsoid.Sphere);
            double distance1 = Distance.getDistanceMeter(source, to, Ellipsoid.WGS84);
            double distance2 = Distance.getDistanceMeter(source, to, Ellipsoid.WGS72);
            log.info("distance" + distance + "\n"
                    + "distance1" + distance1
                    + "distance2" + distance2);

            dayAttList = attService.findByIdAndDate(attendance.getUser_id(), attendance.getDate(), 1);
            //签到
            if (dayAttList.size() == 0) {
                //上班时间是否在规定时间之前
                boolean before = DateCompare.isDateBefore(Time, startTime);
                //迟到
                if (!before) {
                    attendance.setDescribed("迟到");
                } else {
                    attendance.setDescribed("正常");
                }//正常
                attendance.setStatus(1);

                //距离超过1km考勤失败
                if (distance >= address_range) {
                    attendance.setStatus(0);
                    attendance.setDescribed("签到位置异常");
                    attService.insertAttendance(attendance);
                    return new JsonReturn(false);
                }
                success = attService.insertAttendance(attendance);
                return new JsonReturn(success);
            } else if (dayAttList.size() == 1) {
                //签退
                //标准下班时间是否在下班时间之前
                boolean before = DateCompare.isDateBefore(endTime, Time);
                //迟到
                if (!before) {
                    attendance.setDescribed("早退");
                }//正常
                else {
                    attendance.setDescribed("正常");
                }
                attendance.setStatus(1);
                //距离超过1km考勤失败
                if (distance >= address_range) {
                    attendance.setStatus(0);
                    attendance.setDescribed("位置异常");
                    attService.insertAttendance(attendance);
                    return new JsonReturn(false);
                }

                success = attService.insertAttendance(attendance);
                return new JsonReturn(success);
            } else {
                log.info("重复签到");
                return new JsonReturn(false);
            }
        } else {
            //外勤，不计算距离，只判断时间
            dayAttList = attService.findByIdAndDate(attendance.getUser_id(), attendance.getDate(), 1);
            attendance.setStatus(1);
            //签到
            if (dayAttList.size() == 0) {
                //上班时间是否在规定时间之前
                boolean before = DateCompare.isDateBefore(Time, startTime);
                //迟到
                if (!before) {
                    attendance.setDescribed("迟到");
                }//正常
                else {
                    attendance.setDescribed("正常");
                }
                attendance.setStatus(1);
                success = attService.insertAttendance(attendance);
                return new JsonReturn(success);
            } else if (dayAttList.size() == 1) {
                /**
                 * 首先判断要插入的记录和第一条记录哪条是上班，哪条是下班
                 * time是待插入的记录，dayAttList
                 * 判断时间date1是否在时间date2之前
                 */
                boolean morning = DateCompare.isDateBefore(Time, attendance.getDate() + " " + dayAttList.get(0).getTime());
                //补卡的记录是上班记录
                //插入上班记录，更新dayAttList(0)的describe();
                if (morning) {
                    //上班时间是否在规定时间之前
                    boolean before = DateCompare.isDateBefore(Time, startTime);
                    //迟到
                    if (!before) {
                        attendance.setDescribed("迟到");
                    }//正常
                    else {
                        attendance.setDescribed("正常");
                    }
                    //判断dayAttList(0)的下班时间
                    //上班时间是否在规定时间之前
                    boolean after = DateCompare.isDateBefore(endTime, dayAttList.get(0).getTime());
                    //迟到
                    if (!after) {
                        dayAttList.get(0).setDescribed("早退");
                    }//正常
                    else {
                        dayAttList.get(0).setDescribed("正常");
                    }
                    //版本升级的时候把这个定义为事务来做
                    success = attService.insertAttendance(attendance);
                    boolean success1 = attService.updateAttendacne(dayAttList.get(0));
                    return new JsonReturn(success && success1);
                } else {//补卡是下班记录
                    boolean after = DateCompare.isDateBefore(endTime, Time);
                    //迟到
                    if (!after) {
                        attendance.setDescribed("早退");
                    }//正常
                    else {
                        attendance.setDescribed("正常");
                    }
                    success = attService.insertAttendance(attendance);
                    return new JsonReturn(success);
                }
            } else {
                log.info("重复签到");
                return new JsonReturn(false);
            }
        }
    }

    //  @Cacheable(value="selectAllAtt")  //自动根据方法生成缓存,但是缓存时间要配置
    @CrossOrigin(originPatterns = "*", allowCredentials = "true", allowedHeaders = "*", methods = {})
    @RequestMapping("/selectAllAtt")
    public List<Attendance> selectAllAttendance(int user_id) {
        list = attService.findAttendanceByUser_id(user_id);
        //System.out.println(list.get(1).getDescribed());
        return list;
    }

    //人脸比对接口
    @RequestMapping("/faceCompare")
    @Cacheable(value = "faceFeature")
    public Boolean faceCompare(byte[] faceFeatureData, int user_id) {
        if (faceFeatureData == null) {
            log.info("上传的人脸特征为空");
            return null;
        }
        FaceFeature feature = new FaceFeature();
        FaceFeature feature1 = new FaceFeature();
        feature.setFeatureData(faceFeatureData);
        feature1.setFeatureData(userService.findFeatureByUser_id(user_id));
        FeatureCompare featureCompare = new FeatureCompare();
        FaceSimilar faceSimilar1 = featureCompare.compare(feature, feature1);
        if (faceSimilar1.getScore() >= 0.8) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param user_id
     * @return 总上班天数，本月上班天数，本月请假、迟到、早退、出差天数
     */
    @RequestMapping("/statics")
    public List<Integer> getStatics(int user_id) {
        ArrayList<Integer> resultList = new ArrayList<Integer>();
        int i = 0;//总考勤
        int j = 0;//月考勤
        int p = 0;//迟到次数
        int q = 0;//早退次数

        int r = 0;//出差次数
        int z = 0;//请假次数
        int w = 0;//外出次数
        int s = 0;//加班
        int hours = 0;//加班时长

        int allDay;
        int mouthDay;
        //当前年月份
        String date = CurrentTimeUtil.getTime();
        date = date.substring(0, 7);

        list = attService.findAttendanceByUser_id(user_id);
        applyList = applyService.findByUser_id(user_id);
        for (Attendance attendance8 : list) {
            if (attendance8.getStatus() == 1) {
                //总正常考勤次数
                i++;
            }
            if (attendance8.getDate().startsWith(date)) {
                //这个月考勤次数
                j++;
                if (attendance8.getDescribed().equals("迟到")) {
                    //这个月迟到次数
                    p++;
                } else if (attendance8.getDescribed().equals("早退")) {
                    //这个月早退次数
                    q++;
                }
            }
        }
        for (Apply apply : applyList) {
            if (apply.getA_status() == 0 || apply.getA_status() == 2) {
                continue;
            } else {
                if (apply.getA_type().equals("出差")) {
                    r++;
                } else if (apply.getA_type().equals("请假")) {
                    z++;
                } else if (apply.getA_type().equals("外出")) {
                    w++;
                } else if (apply.getA_type().equals("加班")) {
                    s++;
                    hours += apply.getA_hours();
                }
            }
        }
        allDay = i / 2;
        mouthDay = j / 2;
        System.out.println("allDay=" + allDay + "\n" +
                "mouthDay=" + mouthDay + "\n" +
                "迟到" + p + "早退" + q + "出差" + r +
                "请假" + z + "外出" + w + "加班" + s +
                "加班时长：" + hours);
        resultList.add(0, allDay);
        resultList.add(1, mouthDay);
        resultList.add(2, p);
        resultList.add(3, q);
        resultList.add(4, r);
        resultList.add(5, z);
        resultList.add(6, w);
        resultList.add(7, s);
        resultList.add(8, hours);
        return resultList;
    }

    @RequestMapping("/allUserAtt")
    public JsonReturn allUserAtt(HttpServletRequest request) {
        list = attService.selectAllAttendance();
        JsonReturn jsonResult = new JsonReturn();
        jsonResult.putList("arrayList", list);
        jsonResult.setCode(0);
        return jsonResult;
    }

    @RequestMapping("/delete/att")
    public JsonResult deleteAtt(int id) {
        attService.delete(id);
        return new JsonResult(true);
    }

    @RequestMapping("/web/updat/att")
    public JsonReturn updateAtt(int id) {
        boolean flag = attService.updateById(id, 1, "正常");
        return new JsonReturn(flag, 0);
    }

    @RequestMapping("/selectByStatus")
    public List<Attendance> selectBystatus(int status, HttpServletRequest request) {
        //正常1、异常0
        list = attService.findAttendanceByStatus(status);
        return list;
    }

    @RequestMapping("/allApply")
    public List<Apply> selceAllApply() {
        applyList = applyService.findAllApply();
        return applyList;
    }


    @RequestMapping("/mouthStatics")
    public JsonResult mouthStatics(HttpServletRequest request) {
        list = attService.selectAllAttendance();
        applyList = applyService.findAllApply();

        ArrayList<Integer> resultList = new ArrayList<Integer>();
        int i = 0;
        int j = 0;
        int p = 0;
        int q = 0;

        int r = 0;
        int z = 0;
        int w = 0;
        int s = 0;
        int hours = 0;

        int allDay;
        int mouthDay;
        //当前月份
        String mouth;
        String date = CurrentTimeUtil.getTime();
        date = date.substring(0, 6);


        for (Attendance attendance9 : list) {
            if (attendance9.getStatus() == 1) {
                //总正常考勤次数
                i++;
            }
            if (attendance9.getDate().startsWith(date)) {
                //这个月考勤次数
                j++;
                if (attendance9.getDescribed().equals("迟到")) {
                    //这个月迟到次数
                    p++;
                } else if (attendance9.getDescribed().equals("早退")) {
                    //这个月早退次数
                    q++;
                }
            }
        }
        for (Apply apply : applyList) {
            if (apply.getA_status() == 0 || apply.getA_status() == 2) {
                continue;
            } else {
                if (apply.getA_type().equals("出差")) {
                    r++;
                } else if (apply.getA_type().equals("请假")) {
                    z++;
                } else if (apply.getA_type().equals("外出")) {
                    w++;
                } else if (apply.getA_type().equals("加班")) {
                    s++;
                    hours += apply.getA_hours();
                }
            }
        }
        allDay = i / 2;
        mouthDay = j / 2;
        System.out.println("allDay=" + allDay + "\n" +
                "mouthDay=" + mouthDay + "\n" +
                "迟到" + p + "早退" + q + "出差" + r +
                "请假" + z + "外出" + w + "加班" + s +
                "加班时长：" + hours);
        resultList.add(0, allDay);
        resultList.add(1, mouthDay);
        resultList.add(2, p);
        resultList.add(3, q);
        resultList.add(4, r);
        resultList.add(5, z);
        resultList.add(6, w);
        resultList.add(7, s);
        resultList.add(8, hours);
        JsonResult jsonResult = new JsonResult();
        jsonResult.put("resultList", resultList);
        jsonResult.setSuccess(true);
        return jsonResult;
    }

}
